#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
大模型处理模块
基于OpenAI API实现文本摘要和标题生成功能
"""

import os
import json
from openai import OpenAI
from dotenv import load_dotenv

class LLMProcessor:
    def __init__(self, api_key=None, base_url=None, model_name=None):
        """
        初始化大模型处理器
        
        Args:
            api_key (str): API密钥，如果为None则从环境变量获取
            base_url (str): API基础URL，如果为None则从环境变量获取
            model_name (str): 模型名称，如果为None则从环境变量获取
        """
        # 加载环境变量
        load_dotenv()
        
        # 初始化OpenAI客户端
        self.client = OpenAI(
            api_key=api_key or os.getenv("API_KEY"),
            base_url=base_url or os.getenv("BASE_URL")
        )
        
        self.model_name = model_name or os.getenv("MODEL_NAME")
        self.temperature = 0.6
        
        if not all([self.client.api_key, self.client.base_url, self.model_name]):
            raise ValueError("请设置API_KEY、BASE_URL和MODEL_NAME环境变量")
    
    def _fix_json_format(self, json_str):
        """
        修复常见的JSON格式问题
        
        Args:
            json_str (str): 原始JSON字符串
            
        Returns:
            str: 修复后的JSON字符串
        """
        try:
            # 移除可能的markdown代码块标记
            json_str = json_str.replace('```json', '').replace('```', '')
            
            # 移除多余的空白字符
            json_str = json_str.strip()
            
            # 尝试修复常见的引号问题
            # 将中文引号替换为英文引号
            json_str = json_str.replace('"', '"').replace('"', '"')
            json_str = json_str.replace(''', "'").replace(''', "'")
            
            # 修复可能的尾随逗号问题
            import re
            # 移除对象或数组末尾的逗号
            json_str = re.sub(r',(\s*[}\]])', r'\1', json_str)
            
            # 检查JSON字符串是否完整
            if json_str.count('{') > json_str.count('}'):
                # 如果左大括号多于右大括号，尝试补全
                missing_braces = json_str.count('{') - json_str.count('}')
                json_str += '}' * missing_braces
                print(f"[DEBUG] 补全了 {missing_braces} 个右大括号")
            
            # 检查是否有未闭合的字符串
            if json_str.count('"') % 2 != 0:
                # 如果引号数量为奇数，在末尾添加一个引号
                json_str += '"'
                print(f"[DEBUG] 补全了一个引号")
            
            # 检查是否有未闭合的数组
            if json_str.count('[') > json_str.count(']'):
                missing_brackets = json_str.count('[') - json_str.count(']')
                json_str += ']' * missing_brackets
                print(f"[DEBUG] 补全了 {missing_brackets} 个右方括号")
            
            return json_str
        except Exception as e:
            print(f"[DEBUG] JSON修复过程中出错: {str(e)}")
            return json_str
    
    def generate_summary_and_title(self, text, output_file=None):
        """
        生成文本摘要和标题
        
        Args:
            text (str): 需要处理的文本
            output_file (str): 输出文件路径，如果为None则不保存文件
            
        Returns:
            dict: 包含摘要和标题的字典
        """
        response_content = None  # 在函数开始时初始化
        
        try:
            print("开始生成摘要和标题...")
            
            # 构建提示词
            prompt = f"""
请对以下文本进行分析，生成一个简洁的标题和结构化的摘要。

要求：
1. 标题：简洁明了，不超过20个字，能够概括文本的核心内容
2. 摘要：提取文本中的关键信息，用序号列出要点，每个要点简洁明了
   - 只提取重要的事实、决策、结论、数据等关键信息
   - 每个要点控制在30字以内
   - 根据内容情况灵活确定要点数量（1个以上即可）
   - 不要包含"总之"、"结论"等总结性语言
   - 不要包含语气词、感叹词等无关内容
3. 必须严格按照JSON格式返回，不要添加任何解释文字或代码块标记

文本内容：
{text}

请严格按照以下JSON格式返回结果（不要添加任何其他内容）：
{{"title": "标题内容", "summary": ["要点1", "要点2", "要点3"]}}
"""
            
            # 调用LLM生成摘要和标题
            print("正在调用LLM生成摘要和标题...")
            print(f"[DEBUG] 使用模型: {self.model_name}")
            print(f"[DEBUG] 温度参数: {self.temperature}")
            print(f"[DEBUG] 输入文本长度: {len(text)} 字符")
            
            try:
                response = self.client.chat.completions.create(
                    model=self.model_name,
                    messages=[
                        {"role": "system", "content": "你是一个专业的文本摘要助手，擅长提取关键信息并生成结构化摘要。"},
                        {"role": "user", "content": prompt}
                    ],
                    temperature=self.temperature
                )
                print("[DEBUG] LLM API调用成功")
                
                response_content = response.choices[0].message.content
                print(f"[DEBUG] 成功获取响应内容，长度: {len(response_content)} 字符")
                
                # 立即打印原始响应，确保在任何异常之前都能看到
                print(f"\n=== LLM原始响应 ===")
                print(f"响应长度: {len(response_content)} 字符")
                print(f"响应内容:\n{response_content}")
                print("=" * 50)
                
                # 额外的调试信息：显示响应内容的字符编码情况
                print(f"[DEBUG] 响应内容的repr形式: {repr(response_content)}")
                print(f"[DEBUG] 响应内容最后100个字符: {repr(response_content[-100:])}")
                print("=" * 50)
                
            except Exception as api_error:
                print(f"[ERROR] LLM API调用失败: {str(api_error)}")
                print(f"[ERROR] API错误类型: {type(api_error).__name__}")
                raise api_error
            
            # 尝试解析JSON响应
            try:
                # 清理响应内容
                cleaned_response = response_content.strip()
                
                # 移除可能的markdown代码块标记
                if "```json" in cleaned_response:
                    start_idx = cleaned_response.find("```json") + 7
                    end_idx = cleaned_response.find("```", start_idx)
                    if end_idx != -1:
                        cleaned_response = cleaned_response[start_idx:end_idx].strip()
                
                # 移除解释文字，只保留JSON部分
                json_start = cleaned_response.find('{')
                json_end = cleaned_response.rfind('}') + 1
                
                if json_start != -1 and json_end != 0:
                    json_content = cleaned_response[json_start:json_end]
                    print(f"[DEBUG] 提取的JSON内容: {json_content}")
                    
                    # 尝试修复常见的JSON格式问题
                    json_content = self._fix_json_format(json_content)
                    print(f"[DEBUG] 修复后的JSON内容: {json_content}")
                    
                    result_data = json.loads(json_content)
                    
                    # 确保title和summary字段存在且格式正确
                    if "title" not in result_data:
                        result_data["title"] = "录音内容摘要"
                    if "summary" not in result_data:
                        result_data["summary"] = ["摘要生成失败"]
                    
                    # 确保summary是列表格式
                    if isinstance(result_data["summary"], str):
                        # 如果是字符串，尝试按行分割成列表
                        summary_lines = result_data["summary"].split('\n')
                        result_data["summary"] = [line.strip() for line in summary_lines if line.strip()]
                else:
                    # 如果无法找到JSON，则手动构建结果
                    print("[DEBUG] 无法找到JSON格式，使用默认结果")
                    result_data = {
                        "title": "录音内容摘要",
                        "summary": ["无法解析LLM响应中的JSON格式"]
                    }
            except json.JSONDecodeError as e:
                print(f"[ERROR] JSON解析失败: {e}")
                print(f"[ERROR] 原始响应内容: {response_content}")
                
                # JSON解析失败时的备用方案
                result_data = {
                    "title": "录音内容摘要",
                    "summary": ["JSON解析失败，请检查LLM响应格式"]
                }
            
            # 清理摘要内容（移除markdown代码块和解析说明）
            if isinstance(result_data.get("summary"), list):
                cleaned_summary = []
                for item in result_data["summary"]:
                    if isinstance(item, str):
                        # 移除markdown代码块标记
                        cleaned_item = item.replace("```json", "").replace("```", "")
                        # 移除解析说明
                        if not ("### 解析" in cleaned_item or "解析结果" in cleaned_item or "JSON格式" in cleaned_item):
                            cleaned_summary.append(cleaned_item.strip())
                result_data["summary"] = cleaned_summary
            
            # 添加元数据
            result_data.update({
                "status": "success",
                "original_text_length": len(text),
                "model": self.model_name,
                "temperature": self.temperature
            })
            
            print(f"✓ 生成成功！")
            print(f"📝 标题: {result_data.get('title', 'N/A')}")
            
            # 格式化显示摘要（避免重复打印）
            summary = result_data.get('summary', '')
            if isinstance(summary, list):
                formatted_summary = "\n".join([f"{i+1}. {item}" for i, item in enumerate(summary)])
            else:
                formatted_summary = str(summary)
            
            print(f"\n=== 生成的标题和摘要 ===")
            print(f"📝 标题: {result_data.get('title', '录音内容摘要')}")
            print(f"📋 摘要:\n{formatted_summary}")
            print(f"📊 摘要长度: {len(str(summary))} 字符")
            print("=" * 30)
            
            # 保存结果到文件
            if output_file:
                self.save_result(result_data, output_file)
            
            return result_data
            
        except Exception as e:
            error_msg = f"生成摘要和标题时发生异常: {str(e)}"
            print(f"[ERROR] {error_msg}")
            
            # 现在response_content在函数作用域中，一定能访问到
            if response_content is not None:
                print(f"[ERROR] 异常时的LLM响应内容:\n{response_content}")
                print(f"[ERROR] 响应内容长度: {len(response_content)} 字符")
                print(f"[ERROR] 响应内容的repr形式: {repr(response_content)}")
            else:
                print(f"[ERROR] 未能获取到LLM响应内容")
            
            return {
                "status": "error",
                "error": error_msg,
                "original_text_length": len(text) if text else 0
            }
    
    def generate_summary_only(self, text, max_length=500):
        """
        仅生成摘要
        
        Args:
            text (str): 需要处理的文本
            max_length (int): 摘要最大长度
            
        Returns:
            str: 生成的摘要
        """
        try:
            prompt = f"""
请对以下文本生成结构化摘要，提取关键信息并用序号列出：

要求：
- 用序号1、2、3等列出关键要点
- 只提取重要的事实、决策、结论、数据等关键信息
- 每个要点控制在30字以内
- 总共不超过10个要点
- 不要包含"总之"、"结论"等总结性语言
- 不要包含语气词、感叹词等无关内容

文本内容：
{text}
"""
            
            completion = self.client.chat.completions.create(
                model=self.model_name,
                temperature=self.temperature,
                messages=[
                    {
                        "role": "user",
                        "content": prompt
                    }
                ],
                stream=False
            )
            
            return completion.choices[0].message.content.strip()
            
        except Exception as e:
            print(f"生成摘要时发生异常: {str(e)}")
            return f"摘要生成失败: {str(e)}"
    
    def generate_title_only(self, text, max_length=20):
        """
        仅生成标题
        
        Args:
            text (str): 需要处理的文本
            max_length (int): 标题最大长度
            
        Returns:
            str: 生成的标题
        """
        try:
            prompt = f"""
请为以下文本生成一个简洁的标题，不超过{max_length}个字：

{text}
"""
            
            completion = self.client.chat.completions.create(
                model=self.model_name,
                temperature=self.temperature,
                messages=[
                    {
                        "role": "user",
                        "content": prompt
                    }
                ],
                stream=False
            )
            
            return completion.choices[0].message.content.strip()
            
        except Exception as e:
            print(f"生成标题时发生异常: {str(e)}")
            return f"标题生成失败: {str(e)}"
    
    def save_result(self, result_data, output_file):
        """
        保存处理结果到文件
        
        Args:
            result_data (dict): 处理结果数据
            output_file (str): 输出文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_file), exist_ok=True)
            
            # 保存为JSON格式
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(result_data, f, ensure_ascii=False, indent=2)
            
            print(f"处理结果已保存到: {output_file}")
            
        except Exception as e:
            print(f"保存结果失败: {str(e)}")
    
    def set_temperature(self, temperature):
        """
        设置模型温度参数
        
        Args:
            temperature (float): 温度参数，范围0-1
        """
        if 0 <= temperature <= 1:
            self.temperature = temperature
            print(f"温度参数已设置为: {temperature}")
        else:
            print("温度参数必须在0-1之间")

def test_llm_processor():
    """
    测试大模型处理功能
    """
    # 创建处理器实例
    processor = LLMProcessor()
    
    # 测试文本
    test_text = """
    今天我们讨论了人工智能在教育领域的应用。人工智能可以帮助个性化学习，
    根据每个学生的学习进度和能力提供定制化的学习内容。同时，AI还可以协助
    教师进行作业批改和学习分析，提高教学效率。我们还探讨了AI在在线教育
    平台中的作用，包括智能推荐系统和自适应学习路径。总的来说，人工智能
    将会极大地改变传统的教育模式，让学习变得更加高效和个性化。
    """
    
    # 测试生成摘要和标题
    result = processor.generate_summary_and_title(
        test_text, 
        "summaries/test_result.json"
    )
    
    print("\n测试结果:")
    print(json.dumps(result, ensure_ascii=False, indent=2))

if __name__ == "__main__":
    test_llm_processor()